package com.example.kekewaimaibao.order.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.kekewaimaibao.core.constant.RestConstant;
import com.example.kekewaimaibao.order.model.OrderDO;
import com.example.kekewaimaibao.order.service.IOrderService;
import com.example.kekewaimaibao.shop.model.ShopDO;
import com.example.kekewaimaibao.shop.service.IShopService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @author: xuxiang
 * @date: 2022/3/6 22:54 星期日
 * @description:
 * @version: 1.0
 */
@Slf4j
@RestController
@RequestMapping(OrderController.PATH)
@Api(tags = "订单控制层")
@CrossOrigin
public class OrderController {
    public static final String PATH = RestConstant.VERSION_V1 + "/order";

    @Autowired
    IOrderService orderService;

    @Autowired
    IShopService shopService;

    /**
     * 建议弃用全表查询
     * @return
     */
    @ApiOperation(value = "所有订单列表")
    @GetMapping("/list")
    public R list() {
        List<OrderDO> list = orderService.list(null);
        return R.ok(list);
    }

    /**
     * 可根据用户ID或商家ID分页
     * @param current 当前页
     * @param limit 每页数据条数
     * @param orderDO 订单信息
     * @return
     */
    @ApiOperation(value = "分页查询订单信息")
    @PostMapping("/page/{current}/{limit}")
    public R page(@PathVariable long current, @PathVariable long limit,
                  @RequestBody(required = false) OrderDO orderDO) {
        Page<OrderDO> page = new Page<>(current, limit);
        QueryWrapper<OrderDO> wrapper = null;
        if (ObjectUtil.isNotNull(orderDO)) {
            wrapper = new QueryWrapper<>();
            if (ObjectUtil.isNotNull(orderDO.getUserId())) {
                wrapper.eq("user_id", orderDO.getUserId());
            }
            if (ObjectUtil.isNotNull(orderDO.getShopId())) {
                wrapper.eq("shop_id", orderDO.getShopId());
            }
        }
        orderService.page(page, wrapper);
        long total = page.getTotal();
        List<OrderDO> records = page.getRecords();
        Map map = new HashMap<>(4);
        map.put("current", current);
        map.put("limit", limit);
        map.put("total", total);
        map.put("records", records);
        return R.ok(map);
    }

    @ApiOperation(value = "添加订单信息")
    @PostMapping("/save")
    public R save(@RequestBody OrderDO orderDO) {
        boolean flag = orderService.save(orderDO);
        if (flag) {
            return R.ok("后台添加订单信息成功");
        } else {
            return R.failed("后台添加订单信息失败");
        }
    }

    @ApiOperation(value = "删除订单信息")
    @PostMapping("/remove/{id}")
    public R remove(@PathVariable Long id) {
        boolean flag = orderService.removeById(id);
        if (flag) {
            return R.ok("后台删除id为" + id +"的订单信息成功");
        } else {
            return R.failed("后台删除订单信息失败");
        }
    }

    @ApiOperation(value = "更新订单信息")
    @PostMapping("update")
    public R update(@RequestBody OrderDO orderDO) {
        boolean flag = orderService.updateById(orderDO);
        if (flag) {
            return R.ok("后台更新id为" + orderDO.getOrderId() + "的订单信息成功");
        } else {
            return R.failed("后台更新订单信息失败");
        }
    }

    @ApiOperation(value = "批量删除订单信息")
    @PostMapping("/remove-ids/{ids}")
    public R deleteBatchIds(@PathVariable("ids")String[] ids) {
        List<String> list = Arrays.asList(ids);
        boolean flag = orderService.removeByIds(list);
        if (flag) {
            return R.ok("批量删除订单信息成功");
        } else {
            return R.failed("批量删除订单信息失败");
        }
    }

    @ApiOperation(value = "通过id查找订单信息")
    @GetMapping("/get-by-id/{id}")
    public R getByShopId(@PathVariable Long id) {
        OrderDO orderDO = orderService.getById(id);
        if (ObjectUtil.isNotNull(orderDO)) {
            return R.ok(orderDO);
        } else {
            return R.failed("未找到id为" + id + "的订单");
        }
    }

    /**
     * 用户前端获取订单列表
     * 如果current不为0，就按照订单状态获取，否则获取该用户所有订单列表
     * 根据订单的创建时间逆序排序
     * 将订单列表和商家列表传给前端进行订单页面渲染
     * @param userId 用户ID
     * @param current 订单状态（1未支付 2待配送 3配送中 4已送达），0表示全部订单
     * @return
     */
    @ApiOperation(value = "获取用户订单列表")
    @GetMapping("/list-user/{userId}/{current}")
    public R listByUserId(@PathVariable Long userId, @PathVariable Long current) {

        QueryWrapper<OrderDO> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        // 0为全部订单，1为未支付，2为待配送，3为配送中，4为已送达
        if (current != 0) {
            wrapper.eq("status", current);
        }
        // 按照时间逆序
        wrapper.orderByDesc("create_time");
        List<OrderDO> list = orderService.list(wrapper);

        List<ShopDO> shopList = new ArrayList<>();
        for (OrderDO orderDO : list) {
            shopList.add(shopService.getById(orderDO.getShopId()));
        }

        Map<String, Object> map = new HashMap<>();
        map.put("orderList", list);
        map.put("shopList", shopList);

        return R.ok(map);
    }

    /**
     * 商家前端获取订单列表
     * 如果current不为0，就按照订单状态获取，否则获取该商家所有订单列表
     * 根据订单的创建时间升序排序（这个地方以后需要改善，优先展示待配送订单）
     * 将用户地址信息，商家信息封装到订单信息的remark字段（当作订单详情）
     * 将订单列表，用户地址列表，商家列表传给前端进行页面渲染
     * @param shopId 商家ID
     * @param current 订单状态（1未支付 2待配送 3配送中 4已送达），0表示全部订单
     * @return
     */
    @ApiOperation(value = "获取商家订单列表")
    @GetMapping("/list-shop/{shopId}/{current}")
    public R listByShopId(@PathVariable Long shopId, @PathVariable Long current) {
        QueryWrapper<OrderDO> wrapper = new QueryWrapper<>();
        wrapper.eq("shop_id", shopId);
        // 显示全部订单（不需要通过status条件）
        if (current != 0) {
            wrapper.eq("status", current);
        }
        wrapper.orderByAsc("create_time");
        List<OrderDO> orderList = orderService.list(wrapper);

        // 封装List<ShopDO>和List<AddressDO>，让每个订单有一个商家信息和用户地址信息，方便配送时导航
        JSONArray shopAddressInfoArray = new JSONArray();
        JSONArray userAddressInfoArray = new JSONArray();
        // 遍历订单列表，解析remark字段
        for (OrderDO orderDO : orderList) {
//            log.info("orderId ---> {},remark ---> {}", orderDO.getOrderId(), orderDO.getRemark());
            JSONObject remarkJSON = JSONObject.parseObject(orderDO.getRemark());
            // 如果remark为空的话，做容错机制（不选择报错，以防一个订单报错其他订单都报错，让前端判断是否为空即可）
            if (ObjectUtil.isNull(remarkJSON)) {
                shopAddressInfoArray.add(null);
                userAddressInfoArray.add(null);
            }
            JSONObject shopAddressInfoJSON = remarkJSON.getJSONObject("shopAddressInfo");
            JSONObject userAddressInfoJSON = remarkJSON.getJSONObject("userAddressInfo");
            shopAddressInfoArray.add(shopAddressInfoJSON);
            userAddressInfoArray.add(userAddressInfoJSON);
        }

        // 封装订单列表的信息，一个订单包括订单表，商家表，用户地址表的信息
        Map<String, Object> map = new HashMap<>();
        map.put("orderList", orderList);
        map.put("shopAddressList", shopAddressInfoArray);
        map.put("userAddressList", userAddressInfoArray);

//        log.info("map --> {}", map);

        R result = new R();
        result.setCode(200);
        result.setData(map);
        result.setMsg("获取商家订单信息成功");
        return result;
    }

    /**
     * 通过商品列表和数量列表生成订单信息
     * 1. 通过商品列表和商品数量列表计算该订单的包装费用boxCost
     * 2. 封装一个订单对象（这里配送费默认为5，因为还没有考虑过配送费用如何计算）
     *   封装常量：支付方式为未支付，订单状态为未支付
     * 3. 根据封装的订单对象新建一个订单信息
     * @param map 商品列表goodsList、商品数量列表currentList（由前端统计传回）
     * @return
     */
    @ApiOperation(value = "通过商品列表和数量列表生成订单信息")
    @PostMapping("/generate-by-goods")
    public R generateOrderByGoods(@RequestBody Map<String, Object> map) {
        // 从map中获取数据
//        log.info("map ---> {}", JSON.toJSONString(map));

        String goodsString = JSON.toJSONString(map.get("goodsList"));
        JSONArray goodsArray = JSONArray.parseArray(goodsString);

        String currentString = JSON.toJSONString(map.get("currentList"));
        JSONArray currentArray = JSONArray.parseArray(currentString);

        String userId = map.get("userId").toString();
        String shopId = map.get("shopId").toString();

        map.remove("userId");
        map.remove("shopId");
        String remark = JSON.toJSONString(map);

        // 计算包装费用
        Double boxCost = new Double(0);
        if (goodsArray.size() == currentArray.size()) {
            for (int i = 0; i < goodsArray.size(); i++) {
                String goods = goodsArray.get(i).toString();
                JSONObject goodsObject = JSONObject.parseObject(goods);
                Double price = Double.parseDouble(goodsObject.get("price").toString());

                String current = currentArray.get(i).toString();
                Integer count = Integer.parseInt(current);

                boxCost += price * count;
            }
        }

        // 封装一个订单对象
        OrderDO orderDO = new OrderDO();
        orderDO.setBoxCost(boxCost);
        // 配送费默认为 5
        orderDO.setSendCost(5.0);
        orderDO.setUserId(Long.parseLong(userId));
        orderDO.setShopId(Long.parseLong(shopId));
        orderDO.setTotalMoney(boxCost + 5);
        orderDO.setPayMoney(boxCost + 5);
        orderDO.setPayWay("0");
        orderDO.setStatus("1");
        orderDO.setDelFlag("0");
        DateTime dateTime = DateUtil.date();
        orderDO.setCreateTime(dateTime);
        orderDO.setUpdateTime(dateTime);
        orderDO.setRemark(remark);

        // 新增订单
        boolean flag = orderService.save(orderDO);
        log.info("orderDO ---> order_id = " + orderDO.getOrderId());
        if (flag) {
            R result = new R();
            result.setCode(200);
            result.setData(orderDO);
            return result;
        } else {
            return R.failed("通过商品创建订单失败");
        }
    }
}

